index-copy.tsx 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. "use client";
  2. import ButtonOwn from "@/components/ButtonOwn";
  3. import { Link, useRouter } from "@/i18n";
  4. import { useGlobalStore } from "@/stores";
  5. import { Toast } from "antd-mobile";
  6. import clsx from "clsx";
  7. import { useTranslations } from "next-intl";
  8. import { useSearchParams } from "next/navigation";
  9. import { FC, PropsWithChildren, useState } from "react";
  10. import { useFormStatus } from "react-dom";
  11. import { loginAction } from "./action";
  12. import "./style.scss";
  13. /**
  14. * @description 登录注册From表单
  15. * @param {string} type 使用类型
  16. * @param {string} msgError 错误提示 login 或 register
  17. * @param {(params: any) => void} callbackFun 回调方法
  18. */
  19. export interface FromComProps {
  20. type?: string;
  21. msgError?: string;
  22. callbackFun?: (params: any) => void;
  23. }
  24. const initialState = {
  25. message: "",
  26. };
  27. const Submit = (props: { text: string }) => {
  28. const { text } = props;
  29. const { pending, data } = useFormStatus();
  30. return (
  31. <ButtonOwn disabled={pending} type={"submit"} active={true}>
  32. {text}
  33. </ButtonOwn>
  34. );
  35. };
  36. const FromCom: FC<PropsWithChildren<FromComProps>> = ({ type = "login", msgError = "" }) => {
  37. const t = useTranslations("LoginPage");
  38. let [pwdVisible, setPwdVisible] = useState(false);
  39. const searchParams = useSearchParams();
  40. const router = useRouter();
  41. const { setUserInfo, setToken } = useGlobalStore();
  42. const [loginFormStatus, setLoginFormStatus] = useState<{ success?: boolean; message?: string }>(
  43. {}
  44. );
  45. const formAction = async (formData: FormData) => {
  46. Toast.show({ icon: "loading", duration: 3000, maskClickable: false });
  47. const result = await loginAction(formData);
  48. // todo token存放位置在本地, 优化目标: 要做服务端渲染应该获取cookie里面的token
  49. setUserInfo(result.user);
  50. setToken(result.token!);
  51. console.log(`🚀🚀🚀🚀🚀-> in index.tsx on 54`, result);
  52. setLoginFormStatus(result);
  53. Toast.clear();
  54. if (result.success) {
  55. router.replace(searchParams.get("redirect") || "/");
  56. }
  57. };
  58. const onsubmit = (e: React.FormEvent<HTMLFormElement>) => {
  59. e.preventDefault();
  60. const formData = new FormData(e.target as HTMLFormElement);
  61. formAction(formData);
  62. };
  63. const spanClassName = clsx("iconfont", {
  64. "icon-kejian": pwdVisible,
  65. "icon-bukejian": !pwdVisible,
  66. });
  67. return (
  68. <div className="FromCom">
  69. <form onSubmit={onsubmit}>
  70. <div className="phoneInput">
  71. <span className="after">{t("areaCode")}</span>
  72. <input name="userPhone" type="tel" placeholder={t("Celular")} maxLength={11} />
  73. </div>
  74. <div className="passwordInput">
  75. <input
  76. name="pwd"
  77. type={pwdVisible ? "text" : "password"}
  78. placeholder={t("Senha")}
  79. maxLength={12}
  80. />
  81. <span
  82. className={spanClassName}
  83. onClick={() => setPwdVisible(!pwdVisible)}
  84. ></span>
  85. </div>
  86. <div className="btnContent">
  87. <div className="tips"> {loginFormStatus.message} </div>
  88. <Submit text={type == "login" ? "Login" : t("register")} />
  89. </div>
  90. </form>
  91. <div className="link">
  92. {type == "login" ? (
  93. <>
  94. <Link href="/resetPhone">{t("forgetPwd")}</Link>
  95. <Link href="/register">{t("registerGo")}</Link>
  96. </>
  97. ) : (
  98. <Link href="/login" className="active" replace>
  99. {t("loginGo")}
  100. </Link>
  101. )}
  102. </div>
  103. </div>
  104. );
  105. };
  106. export default FromCom;